bitkeeper revision 1.1041.15.1 (40ebc943G6NlOlbW-3EGaR3sQs14kQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 7 Jul 2004 09:58:27 +0000 (09:58 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 7 Jul 2004 09:58:27 +0000 (09:58 +0000)
Revert 1.1051.4.1 (s-expression parser changes).

tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/XendRoot.py
tools/python/xen/xend/sxp.py
tools/python/xen/xm/main.py

index 377e7bb61b21d9bf3e85dc386c2e37f01a587745..619d5754663b03424e4e955340ea8e5e9154b095 100644 (file)
@@ -292,9 +292,6 @@ def vm_restore(src, progress=0):
     if dom < 0:
         raise VmError('restore failed')
     vmconfig = sxp.from_string(d['vmconfig'])
-    if not vmconfig:
-        raise VmError('bad vmconfig s-expression')
-    vmconfig = vmconfig[0]
     vm.config = sxp.child_value(vmconfig, 'config')
     deferred = vm.dom_configure(dom)
     def vifs_cb(val, vm):
@@ -423,8 +420,8 @@ class XendDomainInfo:
         self.config = config
         try:
             self.name = sxp.child_value(config, 'name')
-            self.memory = int(sxp.child_value(config, 'memory') or '128')
-            if sxp.child(config, 'autorestart'):
+            self.memory = int(sxp.child_value(config, 'memory', '128'))
+            if sxp.child(config, 'autorestart', None):
                 self.autorestart = 1
             self.configure_backends()
             image = sxp.child_value(config, 'image')
@@ -457,7 +454,7 @@ class XendDomainInfo:
         """
         devices = []
         for d in sxp.children(self.config, 'device'):
-            dev = sxp.child(d)
+            dev = sxp.child0(d)
             if dev is None: continue
             if name == sxp.name(dev):
                 devices.append(dev)
@@ -588,7 +585,7 @@ class XendDomainInfo:
         if self.recreate: return
         memory = self.memory
         name = self.name
-        cpu = int(sxp.child_value(self.config, 'cpu') or '-1')
+        cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
         print 'init_domain>', memory, name, cpu
         dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
         if dom <= 0:
@@ -653,7 +650,7 @@ class XendDomainInfo:
         devices = sxp.children(self.config, 'device')
         index = {}
         for d in devices:
-            dev = sxp.child(d)
+            dev = sxp.child0(d)
             if dev is None:
                 raise VmError('invalid device')
             dev_name = sxp.name(dev)
@@ -672,7 +669,7 @@ class XendDomainInfo:
         """Set configuration flags if the vm is a backend for netif of blkif.
         """
         for c in sxp.children(self.config, 'backend'):
-            name = sxp.name(sxp.child(c))
+            name = sxp.name(sxp.child0(c))
             if name == 'blkif':
                 self.blkif_backend = 1
             elif name == 'netif':
@@ -754,7 +751,7 @@ def vm_image_linux(vm, image):
     """
     kernel = sxp.child_value(image, "kernel")
     cmdline = ""
-    ip = sxp.child_value(image, "ip") or "dhcp"
+    ip = sxp.child_value(image, "ip", "dhcp")
     if ip:
         cmdline += " ip=" + ip
     root = sxp.child_value(image, "root")
@@ -763,7 +760,7 @@ def vm_image_linux(vm, image):
     args = sxp.child_value(image, "args")
     if args:
         cmdline += " " + args
-    ramdisk = sxp.child_value(image, "ramdisk") or ''
+    ramdisk = sxp.child_value(image, "ramdisk", '')
     vifs = vm.config_devices("vif")
     vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs))
     return vm
@@ -780,7 +777,7 @@ def vm_image_netbsd(vm, image):
     #todo: Same as for linux. Is that right? If so can unify them.
     kernel = sxp.child_value(image, "kernel")
     cmdline = ""
-    ip = sxp.child_value(image, "ip") or "dhcp"
+    ip = sxp.child_value(image, "ip", "dhcp")
     if ip:
         cmdline += "ip=" + ip
     root = sxp.child_value(image, "root")
@@ -809,7 +806,7 @@ def vm_dev_vif(vm, val, index):
     defer = make_vif(vm.dom, vif, vmac, vm.recreate)
     def fn(id):
         dev = xend.netif_dev(vm.dom, vif)
-        devid = sxp.child_value(val, 'id')
+        devid = sxp.attribute(val, 'id')
         if devid:
             dev.setprop('id', devid)
         bridge = sxp.child_value(val, "bridge")
@@ -836,7 +833,7 @@ def vm_dev_vbd(vm, val, index):
     dev = sxp.child_value(val, 'dev')
     if not dev:
         raise VmError('vbd: Missing dev')
-    mode = sxp.child_value(val, 'mode') or 'r'
+    mode = sxp.child_value(val, 'mode', 'r')
     defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
     def fn(vbd):
         dev = xend.blkif_dev(vm.dom, vdev)
@@ -938,7 +935,7 @@ def vm_field_vnet(vm, config, val, index):
         if id is None:
             raise VmError('vnet: missing vif id')
         dev = vm.get_device_by_id('vif', id)
-        #vnet = sxp.child_value(v, 'vnet') or '1'
+        #vnet = sxp.child_value(v, 'vnet', 1)
         #mac = sxp.child_value(dev, 'mac')
         #vif = sxp.child_value(dev, 'vif')
         #vnet_bridge(vnet, mac, vm.dom, 0)
index 3687f57f4a25a9e81143136e588c120a9720e0d3..665f5df29ee2747f43170baa49618f6082f50e7b 100644 (file)
@@ -145,7 +145,7 @@ class XendRoot:
         val    default value (optional, defaults to None)
         returns value
         """
-        return sxp.child_value(self.config, name) or val
+        return sxp.child_value(self.config, name, val=val)
 
 def instance():
     global inst
index 352f7f2933ea3add1ae2477914b3eab88915b2c9..143ba81ab41928095ee9e8c41d2b4e97914da82b 100644 (file)
@@ -21,19 +21,56 @@ from StringIO import StringIO
 __all__ = [
     "mime_type", 
     "ParseError", 
-    "Parser",
-    "show",
+    "Parser", 
+    "atomp", 
+    "show", 
+    "show_xml", 
+    "elementp", 
     "name", 
+    "attributes", 
+    "attribute", 
     "children", 
     "child", 
+    "child_at", 
+    "child0", 
+    "child1", 
+    "child2", 
+    "child3", 
+    "child4", 
     "child_value",
+    "has_id", 
+    "with_id", 
+    "child_with_id", 
+    "elements", 
     "to_string",
     "from_string",
+    "all_from_string",
     "parse", 
     ]
 
 mime_type = "application/sxp"
 
+escapes = {
+    'a': '\a',
+    'b': '\b',
+    't': '\t',
+    'n': '\n',
+    'v': '\v',
+    'f': '\f',
+    'r': '\r',
+    '\\': '\\',
+    '\'': '\'',
+    '\"': '\"'}
+
+k_list_open  = "("
+k_list_close = ")"
+k_attr_open  = "@"
+k_eval       = "!"
+
+escapes_rev = {}
+for k in escapes:
+    escapes_rev[escapes[k]] = k
+
 class ParseError(StandardError):
 
     def __init__(self, parser, value):
@@ -49,6 +86,7 @@ class ParserState:
         self.parent = parent
         self.buf = ''
         self.val = []
+        self.delim = None
         self.fn = fn
 
     def push(self, fn):
@@ -57,19 +95,28 @@ class ParserState:
 class Parser:
 
     def __init__(self):
+        self.error = sys.stderr
         self.reset()
 
     def reset(self):
+        self.val = []
         self.eof = 0
+        self.err = 0
         self.line_no = 0
         self.char_no = 0
-        self.state = self.start_state = ParserState(self.state_start)
+        self.state = None
 
     def push_state(self, fn):
         self.state = self.state.push(fn)
 
     def pop_state(self):
+        val = self.state
         self.state = self.state.parent
+        if self.state and self.state.fn == self.state_start:
+            # Return to start state - produce the value.
+            self.val += self.state.val
+            self.state.val = []
+        return val
 
     def in_class(self, c, s):
         return s.find(c) >= 0
@@ -89,6 +136,12 @@ class Parser:
     def in_printable_class(self, c):
         return self.in_class(c, string.printable)
 
+    def set_error_stream(self, error):
+        self.error = error
+
+    def has_error(self):
+        return self.err > 0
+
     def at_eof(self):
         return self.eof
 
@@ -113,131 +166,439 @@ class Parser:
            self.char_no += 1 
 
         if self.state is None:
-            self.state = ParserState(self.state_start)
-
+            self.begin_start(None)
         self.state.fn(c)
 
     def ready(self):
-        return len(self.start_state.val) > 0
+        return len(self.val) > 0
 
     def get_val(self):
-        v = self.start_state.val[0]
-        self.start_state.val = self.start_state.val[1:]
+        v = self.val[0]
+        self.val = self.val[1:]
         return v
 
     def get_all(self):
-        return self.start_state.val
+        return self.val
+
+    def begin_start(self, c):
+        self.state = ParserState(self.state_start)
 
+    def end_start(self):
+        self.val += self.state.val
+        self.pop_state()
+    
     def state_start(self, c):
-        if self.at_eof() or self.in_space_class(c):
+        if self.at_eof():
+            self.end_start()
+        elif self.in_space_class(c):
             pass
         elif self.in_comment_class(c):
-            self.push_state(self.state_comment)
-        elif c == '(':
-            self.push_state(self.state_list)
-        elif c == ')':
+            self.begin_comment(c)
+        elif c == k_list_open:
+            self.begin_list(c)
+        elif c == k_list_close:
             raise ParseError(self, "syntax error: "+c)
         elif self.in_string_quote_class(c):
-            self.push_state(self.state_string)
-            self.state.buf = c
+            self.begin_string(c)
         elif self.in_printable_class(c):
-            self.push_state(self.state_atom)
-            self.state.buf = c
+            self.begin_atom(c)
         elif c == chr(4):
             # ctrl-D, EOT: end-of-text.
             self.input_eof()
         else:
             raise ParseError(self, "invalid character: code %d" % ord(c))
 
+    def begin_comment(self, c):
+        self.push_state(self.state_comment)
+        self.state.buf += c
+
+    def end_comment(self):
+        self.pop_state()
+    
     def state_comment(self, c):
         if c == '\n' or self.at_eof():
-            self.pop_state()
+            self.end_comment()
+        else:
+            self.state.buf += c
+
+    def begin_string(self, c):
+        self.push_state(self.state_string)
+        self.state.delim = c
 
+    def end_string(self):
+        val = self.state.buf
+        self.state.parent.val.append(val)
+        self.pop_state()
+        
     def state_string(self, c):
         if self.at_eof():
             raise ParseError(self, "unexpected EOF")
-        self.state.buf += c
-        # Look out for non-escaped end delimiter
-        if self.state.buf[0] == c and self.state.buf[-2] != '\\':
-            try: # parse escape sequences but fall back to something simple
-                val = eval(compile(self.state.buf,'','eval'))
-            except:
-                val = self.state.buf[1:-1] # just strip the delimiters
-            self.state.parent.val.append(val)
+        elif c == self.state.delim:
+            self.end_string()
+        elif c == '\\':
+            self.push_state(self.state_escape)
+        else:
+            self.state.buf += c
+
+    def state_escape(self, c):
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        d = escapes.get(c)
+        if d:
+            self.state.parent.buf += d
             self.pop_state()
+        elif c == 'x':
+            self.state.fn = self.state_hex
+            self.state.val = 0
+        else:
+            self.state.fn = self.state_octal
+            self.state.val = 0
+            self.input_char(c)
+
+    def state_octal(self, c):
+        def octaldigit(c):
+            self.state.val *= 8
+            self.state.val += ord(c) - ord('0')
+            self.state.buf += c
+            if self.state.val < 0 or self.state.val > 0xff:
+                raise ParseError(self, "invalid octal escape: out of range " + self.state.buf)
+            if len(self.state.buf) == 3:
+               octaldone()
+               
+        def octaldone():
+            d = chr(self.state.val)
+            self.state.parent.buf += d
+            self.pop_state()
+            
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        elif '0' <= c <= '7':
+            octaldigit(c)
+        elif len(self.buf):
+            octaldone()
+            self.input_char(c)
+
+    def state_hex(self, c):
+        def hexdone():
+            d = chr(self.state.val)
+            self.state.parent.buf += d
+            self.pop_state()
+            
+        def hexdigit(c, d):
+            self.state.val *= 16
+            self.state.val += ord(c) - ord(d)
+            self.state.buf += c
+            if self.state.val < 0 or self.state.val > 0xff:
+                raise ParseError(self, "invalid hex escape: out of range " + self.state.buf)
+            if len(self.state.buf) == 2:
+                hexdone()
+            
+        if self.at_eof():
+            raise ParseError(self, "unexpected EOF")
+        elif '0' <= c <= '9':
+            hexdigit(c, '0')
+        elif 'A' <= c <= 'F':
+            hexdigit(c, 'A')
+        elif 'a' <= c <= 'f':
+            hexdigit(c, 'a')
+        elif len(buf):
+            hexdone()
+            self.input_char(c)
+
+    def begin_atom(self, c):
+        self.push_state(self.state_atom)
+        self.state.buf = c
+
+    def end_atom(self):
+        val = self.state.buf
+        self.state.parent.val.append(val)
+        self.pop_state()
     
     def state_atom(self, c):
-        if (self.at_eof() or
-            self.is_separator(c) or
-            self.in_space_class(c) or
-            self.in_comment_class(c)):
-            val = self.state.buf
-            self.state.parent.val.append(val)
-            self.pop_state()
-            if not self.at_eof():
-                self.input_char(c)
+        if self.at_eof():
+            self.end_atom()
+        elif (self.is_separator(c) or
+              self.in_space_class(c) or
+              self.in_comment_class(c)):
+            self.end_atom()
+            self.input_char(c)
         else:
             self.state.buf += c
 
+    def begin_list(self, c):
+        self.push_state(self.state_list)
+
+    def end_list(self):
+        val = self.state.val
+        self.state.parent.val.append(val)
+        self.pop_state()
+
     def state_list(self, c):
         if self.at_eof():
             raise ParseError(self, "unexpected EOF")
-        elif c == ')':
-            val = self.state.val
-            self.state.parent.val.append(val)
-            self.pop_state()
+        elif c == k_list_close:
+            self.end_list()
         else:
             self.state_start(c)
 
+def atomp(sxpr):
+    """Check if an sxpr is an atom.
+    """
+    if sxpr.isalnum() or sxpr == '@':
+        return 1
+    for c in sxpr:
+        if c in string.whitespace: return 0
+        if c in '"\'\\(){}[]<>$#&%^': return 0
+        if c in string.ascii_letters: continue
+        if c in string.digits: continue
+        if c in '.-_:/~': continue
+        return 0
+    return 1
+    
 def show(sxpr, out=sys.stdout):
     """Print an sxpr in bracketed (lisp-style) syntax.
     """
     if isinstance(sxpr, types.ListType):
-        out.write('(')
+        out.write(k_list_open)
+        i = 0
         for x in sxpr:
+            if i: out.write(' ')
             show(x, out)
-            out.write(' ')
-        out.write(')')
+            i += 1
+        out.write(k_list_close)
+    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
+        out.write(sxpr)
     else:
+        #out.write("'" + str(sxpr) + "'")
         out.write(repr(str(sxpr)))
 
+def show_xml(sxpr, out=sys.stdout):
+    """Print an sxpr in XML syntax.
+    """
+    if isinstance(sxpr, types.ListType):
+        element = name(sxpr)
+        out.write('<%s' % element)
+        for attr in attributes(sxpr):
+            out.write(' %s=%s' % (attr[0], attr[1]))
+        out.write('>')
+        i = 0
+        for x in children(sxpr):
+            if i: out.write(' ')
+            show_xml(x, out)
+            i += 1
+        out.write('</%s>' % element)
+    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
+        out.write(sxpr)
+    else:
+        out.write(str(sxpr))
+
+def elementp(sxpr, elt=None):
+    """Check if an sxpr is an element of the given type.
+
+    sxpr sxpr
+    elt  element type
+    """
+    return (isinstance(sxpr, types.ListType)
+            and len(sxpr)
+            and (None == elt or sxpr[0] == elt))
+
 def name(sxpr):
-    """Get the element name of an sxpr, or None if a bad sxpr.
+    """Get the element name of an sxpr.
+    If the sxpr is not an element (i.e. it's an atomic value) its name
+    is None.
+
+    sxpr
+
+    returns name (None if not an element).
     """
+    val = None
     if isinstance(sxpr, types.StringType):
-        return sxpr
-    if isinstance(sxpr, types.ListType) and len(sxpr):
-        return sxpr[0]
-    return None
+        val = sxpr
+    elif isinstance(sxpr, types.ListType) and len(sxpr):
+        val = sxpr[0]
+    return val
+
+def attributes(sxpr):
+    """Get the attribute list of an sxpr.
+
+    sxpr
+
+    returns attribute list
+    """
+    val = []
+    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
+        attr = sxpr[1]
+        if elementp(attr, k_attr_open):
+            val = attr[1:]
+    return val
+
+def attribute(sxpr, key, val=None):
+    """Get an attribute of an sxpr.
+
+    sxpr sxpr
+    key  attribute key
+    val  default value (default None)
+
+    returns attribute value
+    """
+    for x in attributes(sxpr):
+        if x[0] == key:
+            val = x[1]
+            break
+    return val
 
 def children(sxpr, elt=None):
-    """Get children of an s-expression @sxpr, optionally filtered by
-    element type @elt.
+    """Get children of an sxpr.
+
+    sxpr sxpr
+    elt  optional element type to filter by
+
+    returns children (filtered by elt if specified)
     """
-    if not isinstance(sxpr, types.ListType): return []
-    val = filter(lambda x: isinstance(x, types.ListType) and len(x) > 0, sxpr)
+    val = []
+    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
+        i = 1
+        x = sxpr[i]
+        if elementp(x, k_attr_open):
+            i += 1
+        val = sxpr[i : ]
     if elt:
-        val = filter(lambda x,y=elt: x[0] == y, val)
+        def iselt(x):
+            return elementp(x, elt)
+        val = filter(iselt, val)
     return val
 
-def child(sxpr, elt=None, idx=0):
-    """Get the @idx'th child of the optional filtering type @elt in @sxpr.
+def child(sxpr, elt, val=None):
+    """Get the first child of the given element type.
+
+    sxpr sxpr
+    elt  element type
+    val  default value
     """
-    x = children(sxpr, elt)
-    if len(x) > idx:
-        return x[idx]
-    return None
+    for x in children(sxpr):
+        if elementp(x, elt):
+            val = x
+            break
+    return val
+
+def child_at(sxpr, index, val=None):
+    """Get the child at the given index (zero-based).
 
-def child_value(sxpr, elt=None):
-    """Get the value of the first child of @sxpr with the optional type @elt.
+    sxpr  sxpr
+    index index
+    val   default value
     """
-    x = child(sxpr, elt)
-    if not isinstance(x, types.ListType) or len(x) < 2:
-        return None
-    return x[1]
+    kids = children(sxpr)
+    if len(kids) > index:
+        val = kids[index]
+    return val
+
+def child0(sxpr, val=None):
+    """Get the zeroth child.
+    """
+    return child_at(sxpr, 0, val)
+
+def child1(sxpr, val=None):
+    """Get the first child.
+    """
+    return child_at(sxpr, 1, val)
+
+def child2(sxpr, val=None):
+    """Get the second child.
+    """
+    return child_at(sxpr, 2, val)
+
+def child3(sxpr, val=None):
+    """Get the third child.
+    """
+    return child_at(sxpr, 3, val)
+
+def child4(sxpr, val=None):
+    """Get the fourth child.
+    """
+    return child_at(sxpr, 4, val)
+
+def child_value(sxpr, elt, val=None):
+    """Get the value of the first child of the given element type.
+    Assumes the child has an atomic value.
+
+    sxpr sxpr
+    elt  element type
+    val  default value
+    """
+    kid = child(sxpr, elt)
+    if kid:
+        val = child_at(kid, 0, val)
+    return val
+
+def has_id(sxpr, id):
+    """Test if an s-expression has a given id.
+    """
+    return attribute(sxpr, 'id') == id
+
+def with_id(sxpr, id, val=None):
+    """Find the first s-expression with a given id, at any depth.
+
+    sxpr   s-exp or list
+    id     id
+    val    value if not found (default None)
+
+    return s-exp or val
+    """
+    if isinstance(sxpr, types.ListType):
+        for n in sxpr:
+            if has_id(n, id):
+                val = n
+                break
+            v = with_id(n, id)
+            if v is None: continue
+            val = v
+            break
+    return val
+
+def child_with_id(sxpr, id, val=None):
+    """Find the first child with a given id.
+
+    sxpr   s-exp or list
+    id     id
+    val    value if not found (default None)
+
+    return s-exp or val
+    """
+    if isinstance(sxpr, types.ListType):
+        for n in sxpr:
+            if has_id(n, id):
+                val = n
+                break
+    return val
+
+def elements(sxpr, ctxt=None):
+    """Generate elements (at any depth).
+    Visit elements in pre-order.
+    Values generated are (node, context)
+    The context is None if there is no parent, otherwise
+    (index, parent, context) where index is the node's index w.r.t its parent,
+    and context is the parent's context.
+
+    sxpr   s-exp
+
+    returns generator
+    """
+    yield (sxpr, ctxt)
+    i = 0
+    for n in children(sxpr):
+        if isinstance(n, types.ListType):
+            # Calling elements() recursively does not generate recursively,
+            # it just returns a generator object. So we must iterate over it.
+            for v in elements(n, (i, sxpr, ctxt)):
+                yield v
+        i += 1
 
 def to_string(sxpr):
-    """Convert an s-expression @sxpr to a string.
+    """Convert an sxpr to a string.
+
+    sxpr sxpr
+    returns string
     """
     io = StringIO()
     show(sxpr, io)
@@ -247,14 +608,35 @@ def to_string(sxpr):
     return val
 
 def from_string(str):
-    """Create an sxpr list from a given input string @str.
+    """Create an sxpr by parsing a string.
+
+    str string
+    returns sxpr
+    """
+    io = StringIO(str)
+    vals = parse(io)
+    if vals is []:
+        return None
+    else:
+        return vals[0]
+    
+
+def all_from_string(str):
+    """Create an sxpr list by parsing a string.
+
+    str string
+    returns sxpr list
     """
     io = StringIO(str)
     vals = parse(io)
     return vals
 
 def parse(io):
-    """Completely parse all input from file @io.
+    """Completely parse all input from 'io'.
+
+    io input file object
+    returns list of values, None if incomplete
+    raises ParseError on parse error
     """
     pin = Parser()
     while 1:
@@ -267,11 +649,19 @@ def parse(io):
     else:
         val = None
     return val
-
    
+
 if __name__ == '__main__':
+    print ">main"
     pin = Parser()
-    buf = sys.stdin.read(1024)
-    pin.input(buf)
-    while pin.ready():
-        print '\n****** val=', pin.get_val()
+    while 1:
+        buf = sys.stdin.read(1024)
+        #buf = sys.stdin.readline()
+        pin.input(buf)
+        while pin.ready():
+            val = pin.get_val()
+            print
+            print '****** val=', val
+        if len(buf) == 0:
+            break
+
index 9ae1fb67b8cdda28348fc59d4c11e5322b20bd63..97a36f6711db871ab91940ce01408e5622ce141c 100644 (file)
@@ -246,11 +246,11 @@ class ProgList(Prog):
             info = server.xend_domain(dom)
             d = {}
             d['dom'] = int(dom)
-            d['name'] = sxp.child_value(info, 'name') or '??'
-            d['mem'] = int(sxp.child_value(info, 'memory') or '-1')
-            d['cpu'] = int(sxp.child_value(info, 'cpu') or '-1')
-            d['state'] = sxp.child_value(info, 'state') or '??'
-            d['cpu_time'] = float(sxp.child_value(info, 'cpu_time') or '-1')
+            d['name'] = sxp.child_value(info, 'name', '??')
+            d['mem'] = int(sxp.child_value(info, 'memory', '0'))
+            d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
+            d['state'] = sxp.child_value(info, 'state', '??')
+            d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
             print ("%(dom)-4d %(name)-16s %(mem)7d  %(cpu)3d  %(state)5s  %(cpu_time)7.1f" % d)
 
     def long_list(self, doms):
@@ -424,9 +424,9 @@ class ProgConsoles(Prog):
         for x in l:
             info = server.xend_console(x)
             d = {}
-            d['dom'] = (sxp.child(info, 'dst') or ['dst', '?', '?'])[1]
-            d['port'] = sxp.child_value(info, 'port') or '?'
-            d['id'] = sxp.child_value(info, 'id') or '?'
+            d['dom'] = sxp.child(info, 'dst', ['dst', '?', '?'])[1]
+            d['port'] = sxp.child_value(info, 'port', '?')
+            d['id'] = sxp.child_value(info, 'id', '?')
             print "%(dom)3s %(port)4s %(id)3s" % d
 
 xm.prog(ProgConsoles)